<script type="text/javascript">
    (async function () {
        // convert to i18 text
        function c_ (x) {
            return RED._('@flowfuse/node-red-dashboard/ui-template:ui-template.' + x)
        }
        // TODO: move this to util.js for reuse & unit testing
        function hasProperty (obj, prop) {
            return Object.prototype.hasOwnProperty.call(obj, prop)
        }

        const template = []

        template.push('<template>')
        template.push('    <div>')
        template.push('        <h2>Counter</h2>')
        template.push('        <p>Current Count: {{ count }}</p>')
        template.push('        <p class="my-class">Formatted Count: {{ formattedCount }}</p>')
        template.push('        <v-btn @click="increase()">Increment</v-btn>')
        template.push('    </div>')
        template.push('</template>')
        template.push('')
        template.push('<script>')
        template.push('    export default {')
        template.push('        data() {')
        template.push('            // define variables available component-wide')
        template.push('            // (in <template> and component functions)')
        template.push('            return {')
        template.push('                count: 0')
        template.push('            }')
        template.push('        },')
        template.push('        watch: {')
        template.push('            // watch for any changes of "count"')
        template.push('            count: function () {')
        template.push('                if (this.count % 5 === 0) {')
        template.push('                    this.send({payload: \'Multiple of 5\'})')
        template.push('                }')
        template.push('            }')
        template.push('        },')
        template.push('        computed: {')
        template.push('            // automatically compute this variable')
        template.push('            // whenever VueJS deems appropriate')
        template.push('            formattedCount: function () {')
        template.push('                return this.count + \'Apples\'')
        template.push('            }')
        template.push('        },')
        template.push('        methods: {')
        template.push('            // expose a method to our <template> and Vue Application')
        template.push('            increase: function () {')
        template.push('                this.count++')
        template.push('            }')
        template.push('        },')
        template.push('        mounted() {')
        template.push('            // code here when the component is first loaded')
        template.push('        },')
        template.push('        unmounted() {')
        template.push('            // code here when the component is removed from the Dashboard')
        template.push('            // i.e. when the user navigates away from the page')
        template.push('        }')
        template.push('    }')
        // eslint complaingin about unterminated string literal - need to do this oddity to get around it
        template.push('</' + 'script>')
        template.push('<style>')
        template.push('    /* define any styles here - supports raw CSS */')
        template.push('    .my-class {')
        template.push('        color: red;')
        template.push('    }')
        template.push('</style>')

        const defaultTemplate = template.join('\n')

        RED.nodes.registerType('ui-template', {
            category: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.label.category'),
            color: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.colors.dark'),
            defaults: {
                group: {
                    type: 'ui-group',
                    validate: function () {
                        const valid = (this.templateScope === 'local' && !!this.group) || (this.templateScope !== 'local')
                        return valid
                    }
                }, // for when template is scoped to 'local' (default)
                page: {
                    type: 'ui-page',
                    validate: function () {
                        const valid = (this.templateScope === 'widget:page' && !!this.page) || (this.templateScope !== 'widget:page')
                        return valid
                    }
                }, // for when template is scoped to 'page'
                ui: {
                    type: 'ui-base',
                    validate: function () {
                        const valid = (this.templateScope === 'widget:ui' && !!this.ui) || (this.templateScope !== 'widget:ui')
                        return valid
                    }
                }, // for when template is scoped to 'site'
                name: { value: '' },
                order: { value: 0 },
                width: {
                    value: 0,
                    validate: function (v) {
                        let valid = true
                        if (this.templateScope !== 'global') {
                            const width = v || 0
                            const currentGroup = $('#node-input-group').val() || this.group
                            const groupNode = RED.nodes.node(currentGroup)
                            valid = !groupNode || +width <= +groupNode.width
                            $('#node-input-size').toggleClass('input-error', !valid)
                        }
                        return valid
                    }
                },
                height: { value: 0 },
                head: { value: '' },
                format: { value: defaultTemplate },
                storeOutMessages: { value: true },
                passthru: { value: true },
                resendOnRefresh: { value: true },
                templateScope: { value: 'local' },
                className: { value: '' }
            },
            inputs: 1,
            outputs: 1,
            icon: 'font-awesome/fa-code',
            paletteLabel: 'template',
            label: function () {
                if (this.name) { return this.name }
                const knownLabels = {
                    local: 'template', // widget:group - kept as local for backward compatability
                    'widget:page': 'template',
                    'widget:ui': 'template',
                    'site:style': 'site style',
                    'page:style': 'page style'
                }
                return knownLabels[this.templateScope] || 'template'
            },
            labelStyle: function () { return this.name ? 'node_label_italic' : '' },
            oneditprepare: function () {
                if (RED.editor.__debug === true) {
                    console.log('ui-template: oneditprepare') // useful for locating this code in the browser debugger
                }
                if (hasProperty(RED.editor, 'editText') && typeof RED.editor.editText === 'function') {
                    $('#node-template-expand-editor').show()
                } else {
                    $('#node-template-expand-editor').hide()
                }
                const that = this
                const $templateScope = $('#node-input-templateScope')
    
                // if this groups parent is a subflow template, set the node-config-input-width and node-config-input-height up
                // as typedInputs and hide the elementSizer (as it doesn't make sense for subflow templates)
                if (RED.nodes.subflow(this.z)) {
                    // change inputs from hidden to text & display them
                    $('#node-input-width').attr('type', 'text')
                    $('#node-input-height').attr('type', 'text')
                    $('div.form-row.nr-db-ui-element-sizer-row').hide()
                    $('div.form-row.nr-db-ui-manual-size-row').show()
                } else {
                    // not in a subflow, use the elementSizer
                    $('div.form-row.nr-db-ui-element-sizer-row').show()
                    $('div.form-row.nr-db-ui-manual-size-row').hide()
                    $('#node-input-size').elementSizer({
                        width: '#node-input-width',
                        height: '#node-input-height',
                        group: '#node-input-group'
                    })
                }

                if (typeof this.storeOutMessages === 'undefined') {
                    this.storeOutMessages = true
                    $('#node-input-storeOutMessages').prop('checked', true)
                }

                if (typeof this.passthru === 'undefined') {
                    this.passthru = true
                    $('#node-input-passthru').prop('checked', true)
                }

                if (typeof this.templateScope === 'undefined') {
                    this.templateScope = 'local'
                    $templateScope.val(this.templateScope)
                }

                $templateScope.on('change', function () {
                    $('#template-row-group, #template-row-page, #template-row-ui, #template-row-class').hide()
                    switch ($templateScope.val()) {
                    case 'site:style':
                        $('#template-row-ui').show()
                        that.editor.getSession().setMode('ace/mode/css')
                        break
                    case 'page:style':
                        $('#template-row-page').show()
                        that.editor.getSession().setMode('ace/mode/css')
                        break
                    case 'site:script':
                        $('#template-row-ui').show()
                        that.editor.getSession().setMode('ace/mode/javascript')
                        break
                    case 'page:script':
                        $('#template-row-page').show()
                        that.editor.getSession().setMode('ace/mode/javascript')
                        break
                    case 'widget:ui':
                        $('#template-row-ui').show()
                        that.editor.getSession().setMode('ace/mode/html')
                        break
                    case 'widget:page':
                        $('#template-row-page').show()
                        that.editor.getSession().setMode('ace/mode/html')
                        break
                    default:
                        $('#template-row-group, #template-row-class').show()
                        that.editor.getSession().setMode('ace/mode/html')
                        break
                    }
                    resize.call(that)
                })

                this.editor = RED.editor.createEditor({
                    id: 'node-input-format-editor',
                    mode: 'ace/mode/html',
                    value: $('#node-input-format').val()
                })

                RED.library.create({
                    url: 'uitemplates', // where to get the data from
                    type: 'ui-template', // the type of object the library is for
                    editor: this.editor, // the field name the main text body goes to
                    mode: 'ace/mode/html',
                    fields: ['name']
                })

                this.editor.focus()

                RED.popover.tooltip($('#node-template-expand-editor'), c_('label.expand'))

                $('#node-template-expand-editor').on('click', function (e) {
                    e.preventDefault()
                    const value = that.editor.getValue()
                    RED.editor.editText({
                        mode: $templateScope.val() === 'global' ? 'css' : 'html',
                        value,
                        width: 'Infinity',
                        cursor: that.editor.getCursorPosition(),
                        complete: function (v, cursor) {
                            that.editor.setValue(v, -1)
                            that.editor.gotoLine(cursor.row + 1, cursor.column, false)
                            setTimeout(function () { that.editor.focus() }, 300)
                        }
                    })
                })

                // use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
                $('.ui-node-popover-title').tooltip({
                    show: {
                        effect: 'slideDown',
                        delay: 150
                    }
                })

                $templateScope.trigger('change') // trigger the change event to hide/show the group/dashboard row
            },
            oneditsave: function () {
                const annot = this.editor.getSession().getAnnotations()
                this.noerr = 0
                $('#node-input-noerr').val(0)
                for (let k = 0; k < annot.length; k++) {
                    if (annot[k].type === 'error') {
                        $('#node-input-noerr').val(annot.length)
                        this.noerr = annot.length
                    }
                }
                $('#node-input-format').val(this.editor.getValue())
                this.editor.destroy()
                delete this.editor

                // ensure we only have one of group/page/dashboard defined
                const scope = $('#node-input-templateScope').val()
                if (scope === 'local') {
                    $('#node-input-ui').val('_ADD_')
                    $('#node-input-page').val('_ADD_')
                } else if (scope === 'widget:page') {
                    $('#node-input-ui').val('_ADD_')
                    $('#node-input-group').val('_ADD_')
                } else if (scope === 'widget:ui') {
                    $('#node-input-page').val('_ADD_')
                    $('#node-input-group').val('_ADD_')
                } else if (scope === 'site:style') {
                    $('#node-input-page').val('_ADD_')
                    $('#node-input-group').val('_ADD_')
                } else if (scope === 'page:style') {
                    $('#node-input-ui').val('_ADD_')
                    $('#node-input-group').val('_ADD_')
                }
            },
            oneditcancel: function () {
                this.editor.destroy()
                delete this.editor
            },
            oneditresize: resize.bind(this)
        })

        function resize (size) {
            const rows = $('#dialog-form>div:not(.node-text-editor-row)')
            let fixRowsHeight = 0
            for (let i = 0; i < rows.size(); i++) {
                fixRowsHeight += $(rows[i]).height()
            }
            const dialogHeight = $('#dialog-form').height()
            const height = dialogHeight - fixRowsHeight
            $('.node-text-editor').css('height', height + 'px')
            if (RED.editor.__debug === true) {
                console.log('dialogHeight', dialogHeight, 'fixRowsHeight', fixRowsHeight, 'height', height, 'editorRow')
            }
            this.editor && this.editor.resize()
        }
    })()
</script>

<script type="text/html" data-template-name="ui-template">
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
        <div style="display:inline-block; width:calc(100% - 105px)">
            <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
        </div>
    </div>
    <div class="form-row">
        <label for="node-input-temlplateScope"><i class="fa fa-dot-circle-o"></i> <span data-i18n="ui-template.label.scope"></span></label>
        <select style="width:76%" id="node-input-templateScope">
            <option value="local" data-i18n="ui-template.label.widget-group"></option>
            <option value="widget:page" data-i18n="ui-template.label.widget-page"></option>
            <option value="widget:ui" data-i18n="ui-template.label.widget-ui"></option>
            <option value="site:style" data-i18n="ui-template.label.site-style"></option>
            <option value="page:style" data-i18n="ui-template.label.page-style"></option>
            <!-- FUTURE? <option value="site:script" data-i18n="ui-template.label.site-script"></option>
            <option value="page:script" data-i18n="ui-template.label.page-script"></option> -->
        </select>
    </div>
    <div id="template-row-ui" class="form-row">
        <label for="node-input-ui"><i class="fa fa-bookmark"></i> <span data-i18n="ui-template.label.ui"></label>
        <input type="text" id="node-input-ui">
    </div>
    <div id="template-row-page" class="form-row">
        <label for="node-input-page"><i class="fa fa-bookmark"></i> <span data-i18n="ui-template.label.page"></label>
        <input type="text" id="node-input-page">
    </div>
    <div id="template-row-group" class="form-row">
        <label for="node-input-group"><i class="fa fa-table"></i> <span data-i18n="ui-template.label.group"></label>
        <input type="text" id="node-input-group">
    </div>
    <div class="form-row nr-db-ui-element-sizer-row">
        <label><i class="fa fa-object-group"></i> <span data-i18n="ui-template.label.size">Size</label>
        <button class="editor-button" id="node-input-size"></button>
    </div>
    <div class="form-row nr-db-ui-manual-size-row">
        <label><i class="fa fa-arrows-h"></i> <span data-i18n="ui-template.label.width">Width</label>
        <input type="hidden" id="node-input-width">
    </div>
    <div class="form-row nr-db-ui-manual-size-row">
        <label><i class="fa fa-arrows-v"></i> <span data-i18n="ui-template.label.height">Height</label>
        <input type="hidden" id="node-input-height">
    </div>
    <!--<div class="form-row" id="template-row-size">
        <label><i class="fa fa-object-group"></i> <span data-i18n="ui-template.label.size"></span></label>
        <input type="hidden" id="node-input-width">
        <input type="hidden" id="node-input-height">
        <button class="editor-button" id="node-input-size"></button>
    </div>-->
    <div class="form-row">
        <label for="node-input-className"><i class="fa fa-code"></i> <span data-i18n="ui-template.label.className"></label>
        <div style="display: inline;">
            <input style="width: 70%;" type="text" id="node-input-className" data-i18n="[placeholder]ui-template.label.classNamePlaceholder" style="flex-grow: 1;">
            <a
                data-html="true"
                title="Dynamic Property: Send msg.class to append new classes to this widget. NOTE: classes set at runtime will be applied in addition to any class(es) set in the nodes class field."
                class="red-ui-button ui-node-popover-title"
                style="margin-left: 4px; cursor: help; font-size: 0.625rem; border-radius: 50%; width: 24px; height: 24px; display: inline-flex; justify-content: center; align-items: center;">
                <i style="font-family: ui-serif;">fx</i>
            </a>
        </div>
    </div>
    <div class="form-row" style="margin-bottom:0px;">
        <label for="node-input-format" style="width:110px;"><i class="fa fa-copy"></i> <span data-i18n="ui-template.label.template"></span></label>
        <input type="hidden" id="node-input-format">
        <button id="node-template-expand-editor" class="red-ui-button red-ui-button-small" style="float:right"><i class="fa fa-expand"></i></button>
    </div>
    <div class="form-row node-text-editor-row" style="display: block;">
        <div style="height:250px; min-height:100px" class="node-text-editor" id="node-input-format-editor" ></div>
    </div>
    <div id="template-pass-store">
        <div class="form-row" style="margin-bottom:0px;">
            <input type="checkbox" id="node-input-passthru" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
            <label for="node-input-passthru" style="width:70%;"> <span data-i18n="ui-template.label.pass-through"></span></label>
        </div>
    </div>
    <!--<div class="form-row" style="margin-bottom:0px;">
            <input type="checkbox" id="node-input-storeOutMessages" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
            <label for="node-input-storeOutMessages" style="width:70%;"> <span data-i18n="ui-template.label.store-state"></span></label>
        </div>
        <div class="form-row" style="margin-bottom:0px;">
            <input type="checkbox" id="node-input-resendOnRefresh" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
            <label for="node-input-resendOnRefresh" style="width:70%;"> <span data-i18n="ui-template.label.resend"></span></label>
        </div>
    </div> -->
</script>